﻿using AKBGame.Constant;
using AKBGame.Object;
using AKBGame.Service;
using AKBGame.Util;
using HtmlAgilityPack;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace AKBGame
{
    public partial class MainForm : Form
    {
        public List<MemberLove> MemberLoveList { get; set; }
        public List<LoveSpecial> LoveSpecialList { get; set; }
        public List<Member> MemberList { get; set; }

        public List<ClothIDMapping> ClothIDMappingList { get; set; }
        public List<MemberIDMapping> MemberIDMappingList { get; set; }
        public List<SkillEffectIDMapping> SkillEffectIDMappingList { get; set; }
        public List<SkillTriggerIDMapping> SkillTriggerIDMappingList { get; set; }
        public List<PerformaceBoostMapping> PerformaceBoostMappingList { get; set; }
        public List<Song> SongList { get; set; }
        public List<Event> EventList { get; set; }
        public List<LevelExperience> LevelExperienceList { get; set; }
        
        public MainForm()
        {
            InitializeComponent();

            try
            {
                GetLoveSpecial();

                MemberLoveList = XMLHelper.LoadFromXML<List<MemberLove>>(@"Data\MemberLove.xml");
                FillMemberLoveListView();
                GetClothIDMapping();

                SkillEffectIDMappingList = XMLHelper.LoadFromXML<List<SkillEffectIDMapping>>(@"Data\SkillEffectIDMapping.xml");
                SkillTriggerIDMappingList = XMLHelper.LoadFromXML<List<SkillTriggerIDMapping>>(@"Data\SkillTriggerIDMapping.xml");
                PerformaceBoostMappingList = XMLHelper.LoadFromXML<List<PerformaceBoostMapping>>(@"Data\PerformaceBoostMapping.xml");
                LevelExperienceList = XMLHelper.LoadFromXML<List<LevelExperience>>(@"Data\Experience.xml");

                try
                {
                    EventList = XMLHelper.LoadFromXML<List<Event>>(@"Data\Event.xml");
                    FillEventListView();
                }
                catch (Exception ex)
                {
                    EventList = new List<Event>();
                }

                GetMemberIDMapping();
                comboBoxSelectedGroup.SelectedIndex = 0;
                GetMember();
                
                SongList = new List<Song>();
                SongList = XMLHelper.LoadFromXML<List<Song>>(@"Data\Song.xml");
                FillSongListView(SongList);
            }
            catch (Exception ex)
            {

            }
        }

        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch ((sender as TabControl).SelectedIndex)
            {
                case 0:
                    break;
                case 1:
                    break;
                default:
                    break;
            }
        }

        private void GetLoveFromServer()
        {
            try
            {
                MemberLoveList = new List<MemberLove>();

                WebClient client = new WebClient();
                MemoryStream ms = new MemoryStream(client.DownloadData(string.Format(LinkConstant.LoveAPI, textBoxSesID.Text, textBoxAolId.Text)));

                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                doc.Load(ms, Encoding.UTF8);

                HtmlAgilityPack.HtmlDocument docStockContext = new HtmlAgilityPack.HtmlDocument();

                docStockContext.LoadHtml(doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/table[1]/tbody[1]").InnerHtml);

                //member rows
                HtmlNodeCollection memberRows = docStockContext.DocumentNode.SelectNodes("./tr");

                foreach (HtmlNode memberRow in memberRows)
                {
                    string memberName = memberRow.SelectSingleNode("./td[2]/a[1]").InnerHtml;
                    string loveCount = memberRow.SelectSingleNode("./td[3]").InnerHtml;

                    MemberLove memberLove = new MemberLove();
                    memberLove.MemberName = memberName.Replace(" ", "");
                    memberLove.LoveCount = int.Parse(loveCount.Replace(",", ""));
                    MemberLoveList.Add(memberLove);
                }

                FillMemberLoveListView();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Retrieve error!");
            }
        }

        private void FillMemberLoveListView()
        {
            listViewLove.Items.Clear();

            foreach (MemberLove memberLove in MemberLoveList)
            {
                int stoneDifferent = CalculateStoneDifferent(memberLove.LoveCount);
                int heartDifferent = CalculateHeartDifferent(memberLove.LoveCount);
                int specialDifferent = CalculateSpecialDifferent(memberLove.LoveCount);

                string[] row = { memberLove.MemberName, memberLove.LoveCount.ToString(), stoneDifferent.ToString(), heartDifferent.ToString(), specialDifferent.ToString() };
                var listViewItem = new ListViewItem(row);
                listViewLove.Items.Add(listViewItem);
            }

            listViewLove.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewLove.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void GetLoveSpecial()
        {
            LoveSpecialList = XMLHelper.LoadFromXML<List<LoveSpecial>>(@"Data\LoveSpecial.xml");

            foreach (LoveSpecial loveSpecial in LoveSpecialList)
            {
                string[] row = { loveSpecial.LoveCount.ToString(), loveSpecial.SpecialItem };
                var listViewItem = new ListViewItem(row);
                listViewLoveSpecial.Items.Add(listViewItem);
            }

            listViewLoveSpecial.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewLoveSpecial.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private int CalculateStoneDifferent(int loveCount)
        {
            if (LoveSpecialList != null && LoveSpecialList.Count > 0)
            {
                LoveSpecial loveSpecial = LoveSpecialList.Where(o => o.SpecialItem.Contains("音石")
                    && o.LoveCount > loveCount).FirstOrDefault();

                return loveSpecial == null ? -1 : loveSpecial.LoveCount - loveCount;
            }

            else
            {
                return -1;
            }
        }

        private int CalculateHeartDifferent(int loveCount)
        {
            if (LoveSpecialList != null && LoveSpecialList.Count > 0)
            {
                LoveSpecial loveSpecial = LoveSpecialList.Where(o => o.SpecialItem.Contains("ハート")
                    && o.LoveCount > loveCount).FirstOrDefault();

                return loveSpecial == null ? -1 : loveSpecial.LoveCount - loveCount;
            }

            else
            {
                return -1;
            }
        }

        private int CalculateSpecialDifferent(int loveCount)
        {
            if (LoveSpecialList != null && LoveSpecialList.Count > 0)
            {
                LoveSpecial loveSpecial = LoveSpecialList.Where(o => o.LoveCount > loveCount).FirstOrDefault();
                return loveSpecial == null ? -1 : loveSpecial.LoveCount - loveCount;
            }

            else
            {
                return -1;
            }
        }

        private void buttonRefresh_Click(object sender, EventArgs e)
        {
            GetLoveFromServer();
            XMLHelper.SaveToXML<List<MemberLove>>(MemberLoveList, @"Data\MemberLove.xml");
        }

        private void listViewLove_Click(object sender, EventArgs e)
        {
            HighlightLoveSpecialByMember();
        }

        private void HighlightLoveSpecialByMember()
        {
            var selectedItem = listViewLove.SelectedItems[0];

            int nextSpecialValue = int.Parse(selectedItem.SubItems[1].Text) + int.Parse(selectedItem.SubItems[4].Text);

            foreach (ListViewItem item in listViewLoveSpecial.Items)
            {
                item.BackColor = Color.Transparent;

                if (item.SubItems[0].Text == nextSpecialValue.ToString())
                {
                    item.BackColor = Color.Orange;
                }
            }
        }

        private void listViewLove_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            int sortColumn;
            sortColumn = listViewLove.Tag == null ? 0 : (int)listViewLove.Tag;

            if (e.Column != sortColumn)
            {
                sortColumn = e.Column;
                listViewLove.Sorting = SortOrder.Ascending;
            }

            else
            {
                // Determine what the last sort order was and change it.
                if (listViewLove.Sorting == SortOrder.Ascending)
                    listViewLove.Sorting = SortOrder.Descending;
                else
                    listViewLove.Sorting = SortOrder.Ascending;
            }

            listViewLove.Tag = sortColumn;

            // Call the sort method to manually sort.
            //listViewLove.Sort();
            this.listViewLove.ListViewItemSorter = new ListViewLoveComparer(e.Column, listViewLove.Sorting, MemberIDMappingList);
        }

        private void GetMember()
        {
            string memberStream = null;

            if(comboBoxSelectedGroup.Text == GroupName.SKE)
                memberStream = TextFileHelper.LoadString(@"Data\Member.txt");
            else if(comboBoxSelectedGroup.Text == GroupName.HKT)
                memberStream = TextFileHelper.LoadString(@"Data\Member_HKT.txt");
            else if (comboBoxSelectedGroup.Text == GroupName.NMB)
                memberStream = TextFileHelper.LoadString(@"Data\Member_NMB.txt");
            else if (comboBoxSelectedGroup.Text == GroupName.AKB)
                memberStream = TextFileHelper.LoadString(@"Data\Member_AKB.txt");

            string memberJSON = GZipStreamHelper.UncompressString(memberStream);

            MemberList = new List<Member>();
            
            RootObject memberList = JsonConvert.DeserializeObject<RootObject>(memberJSON);
            foreach (LIST memberJSONObject in memberList.RES_DATA.LIST)
            {
                Member member = new Member();
                member.MemberID = memberJSONObject.MEMBER_ID;

                MemberIDMapping mapping = MemberIDMappingList.FirstOrDefault(o => o.ID == member.MemberID);
                member.MemberName = mapping == null ? member.MemberID.ToString() : mapping.Name;
                member.MemberNameHiragana = mapping == null ? member.MemberID.ToString() : mapping.NameHiragana;

                member.ClothID = memberJSONObject.VARIATION_ID;
                ClothIDMapping clothIDMapping = ClothIDMappingList.FirstOrDefault(o => o.ID == memberJSONObject.VARIATION_ID);
                member.ClothName = clothIDMapping == null ? memberJSONObject.VARIATION_ID.ToString() : clothIDMapping.Cloth;

                member.Performance = memberJSONObject.PERFORMANCE;
                member.PerformanceMax = memberJSONObject.PERFORMANCE_MAX;
                member.Mental = memberJSONObject.MENTAL;
                member.MentalMax = memberJSONObject.MENTAL_MAX;

                member.Color = MemberColorHelper.GetMemberColor(memberJSONObject.ATTRIBUTE);
                member.Rarity = memberJSONObject.RARITY;
                member.Growth = memberJSONObject.GROWTH_AVERAGE;

                member.SkillEffectID = memberJSONObject.SKILL_EFFECT;
                SkillEffectIDMapping skillEffectIDMapping = SkillEffectIDMappingList.FirstOrDefault(o => o.ID == memberJSONObject.SKILL_EFFECT);
                member.SkillEffect = skillEffectIDMapping == null ? memberJSONObject.SKILL_EFFECT.ToString() : skillEffectIDMapping.SkillEffect;

                member.SkillTriggerID = memberJSONObject.SKILL_TRIGGER;
                SkillTriggerIDMapping skillTriggerIDMapping = SkillTriggerIDMappingList.FirstOrDefault(o => o.ID == memberJSONObject.SKILL_TRIGGER);
                member.SkillTrigger = skillTriggerIDMapping == null ? memberJSONObject.SKILL_TRIGGER.ToString() : skillTriggerIDMapping.SkillTrigger;

                int boost = 0;
                MemberLove memberLove = MemberLoveList.FirstOrDefault(o => o.MemberName == member.MemberName);
                if (memberLove != null)
                {
                    PerformaceBoostMappingList.ForEach(o => boost += (memberLove.LoveCount >= o.LoveCount ? o.PerformaceBoost : 0));
                }

                member.PerformanceBoost = boost;
                MemberList.Add(member);
            }

            //MemberList = MemberList.OrderBy(o => o.MemberNameHiragana).ToList();
            FillMemberListView(MemberList);
        }

        private void FillMemberListView(List<Member> inputMemberList)
        {
            listViewMember.Items.Clear();

            foreach (Member member in inputMemberList)
            {
                string[] row = { member.MemberName.ToString(), 
                                   member.ClothName.ToString(),
                                   member.Color.ToString(), 
                                   member.Rarity.ToString(), 
                                   member.Performance.ToString(),
                                   member.PerformanceBoost.ToString(),
                                   (member.Performance + member.PerformanceBoost).ToString(),
                                   member.Growth.ToString(),
                                   member.SkillEffect.ToString(),
                                   member.SkillTrigger.ToString()
                               };

                var listViewItem = new ListViewItem(row);
                listViewMember.Items.Add(listViewItem);
            }

            listViewMember.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewMember.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void listViewMember_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            int sortColumn;

            sortColumn = listViewMember.Tag == null ? 0 : (int)listViewMember.Tag;

            if (e.Column != sortColumn)
            {
                sortColumn = e.Column;
                listViewMember.Sorting = SortOrder.Ascending;
            }

            else
            {
                // Determine what the last sort order was and change it.
                if (listViewMember.Sorting == SortOrder.Ascending)
                    listViewMember.Sorting = SortOrder.Descending;
                else
                    listViewMember.Sorting = SortOrder.Ascending;
            }

            listViewMember.Tag = sortColumn;

            // Call the sort method to manually sort.
            //listViewMember.Sort();
            this.listViewMember.ListViewItemSorter = new ListViewMemberComparer(e.Column, listViewMember.Sorting, MemberIDMappingList);
        }

        private void FilterMemberListView()
        {
            List<Member> resultMemberList = new List<Member>();
            resultMemberList.AddRange(MemberList);

            if (!checkBoxRed.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Color != "Red").ToList();
            }

            if (!checkBoxBlue.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Color != "Blue").ToList();
            }

            if (!checkBoxGreen.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Color != "Green").ToList();
            }

            if (!checkBoxYellow.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Color != "Yellow").ToList();
            }

            if (!checkBoxPurple.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Color != "Purple").ToList();
            }

            if (!checkBoxStar1.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 1).ToList();
            }

            if (!checkBoxStar2.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 2).ToList();
            }

            if (!checkBoxStar3.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 3).ToList();
            }

            if (!checkBoxStar4.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 4).ToList();
            }

            if (!checkBoxStar5.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 5).ToList();
            }

            if (!checkBoxStar6.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 6).ToList();
            }

            if (!checkBoxStar7.Checked)
            {
                resultMemberList = resultMemberList.Where(o => o.Rarity != 7).ToList();
            }

            if (!checkBoxScoreUp.Checked)
            {
                resultMemberList = resultMemberList.Where(o => !(1 <= o.SkillEffectID && o.SkillEffectID <= 5)).ToList();
            }

            if (!checkBoxRestore.Checked)
            {
                resultMemberList = resultMemberList.Where(o => !(6 <= o.SkillEffectID && o.SkillEffectID <= 10)).ToList();
            }

            if (!checkBoxMental.Checked)
            {
                resultMemberList = resultMemberList.Where(o => !(11 <= o.SkillEffectID && o.SkillEffectID <= 15)).ToList();
            }

            if (!checkBoxDecision.Checked)
            {
                resultMemberList = resultMemberList.Where(o => !(15 <= o.SkillEffectID && o.SkillEffectID <= 20)).ToList();
            }

            if (!checkBoxOther.Checked)
            {
                resultMemberList = resultMemberList.Where(o => !(21 <= o.SkillEffectID && o.SkillEffectID <= 99)).ToList();
            }

            FillMemberListView(resultMemberList);
        }

        private void buttonFilter_Click(object sender, EventArgs e)
        {
            FilterMemberListView();
        }

        private void listViewLove_KeyUp(object sender, KeyEventArgs e)
        {
            HighlightLoveSpecialByMember();
        }

        private void buttonSelectAll_Click(object sender, EventArgs e)
        {
            checkBoxRed.Checked = true;
            checkBoxBlue.Checked = true;
            checkBoxGreen.Checked = true;
            checkBoxYellow.Checked = true;
            checkBoxPurple.Checked = true;
            checkBoxStar1.Checked = true;
            checkBoxStar2.Checked = true;
            checkBoxStar3.Checked = true;
            checkBoxStar4.Checked = true;
            checkBoxStar5.Checked = true;
            checkBoxStar6.Checked = true;
            checkBoxStar7.Checked = true;
            checkBoxScoreUp.Checked = true;
            checkBoxRestore.Checked = true;
            checkBoxMental.Checked = true;
            checkBoxDecision.Checked = true;
            checkBoxOther.Checked = true;
        }

        private void buttonUnselectAll_Click(object sender, EventArgs e)
        {
            checkBoxRed.Checked = false;
            checkBoxBlue.Checked = false;
            checkBoxGreen.Checked = false;
            checkBoxYellow.Checked = false;
            checkBoxPurple.Checked = false;
            checkBoxStar1.Checked = false;
            checkBoxStar2.Checked = false;
            checkBoxStar3.Checked = false;
            checkBoxStar4.Checked = false;
            checkBoxStar5.Checked = false;
            checkBoxStar6.Checked = false;
            checkBoxStar7.Checked = false;
            checkBoxScoreUp.Checked = false;
            checkBoxRestore.Checked = false;
            checkBoxMental.Checked = false;
            checkBoxDecision.Checked = false;
            checkBoxOther.Checked = false;
        }

        private void buttonAddSong_Click(object sender, EventArgs e)
        {
            AddSongForm addUserForm = new AddSongForm();
            addUserForm.SongUpdated += new AddSongForm.SongUpdateHandler(AddSongForm_ButtonClicked);
            addUserForm.Show();
        }

        private void AddSongForm_ButtonClicked(object sender, AKBGame.AddSongForm.SongUpdateEventArgs e)
        {
            if (SongList.Select(o => o.RhythmDataMappingName).Contains(e.Song.RhythmDataMappingName))
            {
                var confirmResult = MessageBox.Show("The Song is already exist. Do you want to overwrite the rhythm?", "Song already exist", MessageBoxButtons.YesNo);

                if (confirmResult == DialogResult.Yes)
                {
                    Song song = SongList.Single(o => o.RhythmDataMappingName == e.Song.RhythmDataMappingName);
                    song.RhythmDataList = e.Song.RhythmDataList;
                }
            }

            else
            {
                SongList.Add(e.Song);
            }

            XMLHelper.SaveToXML<List<Song>>(SongList, @"Data\Song.xml");
            FillSongListView(SongList);
            
        }

        private void FillSongListView(List<Song> inputSongList)
        {
            listViewSongCalculator.Items.Clear();

            foreach (Song song in inputSongList)
            {
                string[] row = { song.RhythmDataMappingName, song.SongName };

                var listViewItem = new ListViewItem(row);
                listViewSongCalculator.Items.Add(listViewItem);
            }

            listViewSongCalculator.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewSongCalculator.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void listViewSongCalculator_Click(object sender, EventArgs e)
        {
            SelectSong();
        }

        private void SelectSong()
        {
            var selectedItem = listViewSongCalculator.SelectedItems[0];

            Song selectedSong = SongList.Single(o => o.RhythmDataMappingName == selectedItem.SubItems[0].Text);
            textBoxSongName.Text = selectedSong.SongName;
            textBoxHighScore.Text = selectedSong.HighScore.ToString();

            //Fill Rhythm Data ListView
            FillListViewRhythmData(selectedSong);

            //Fill combo boxes
            FillSongComboBoxOption(MemberList);
            comboBoxHSUnitM1.Text = selectedSong.HighScoreUnitM1;
            comboBoxHSUnitM2.Text = selectedSong.HighScoreUnitM2;
            comboBoxHSUnitM3.Text = selectedSong.HighScoreUnitM3;
            comboBoxHSUnitM4.Text = selectedSong.HighScoreUnitM4;
            comboBoxHSUnitM5.Text = selectedSong.HighScoreUnitM5;

            comboBoxHSUnitCloth1.Text = selectedSong.HighScoreUnitCloth1;
            comboBoxHSUnitCloth2.Text = selectedSong.HighScoreUnitCloth2;
            comboBoxHSUnitCloth3.Text = selectedSong.HighScoreUnitCloth3;
            comboBoxHSUnitCloth4.Text = selectedSong.HighScoreUnitCloth4;
            comboBoxHSUnitCloth5.Text = selectedSong.HighScoreUnitCloth5;

            //Fill main color combo box
            FillMainColorComboBoxOption();
            comboBoxSongMainColor.Text = MemberColorHelper.GetMemberColor(selectedSong.MainColor);

            //Fill bonus combo box
            FillClothBonusComboBoxOption();

            List<ComboBox> clothComboBoxList = new List<ComboBox>();
            clothComboBoxList.Add(comboBoxClothBonus1);
            clothComboBoxList.Add(comboBoxClothBonus2);
            clothComboBoxList.Add(comboBoxClothBonus3);
            clothComboBoxList.Add(comboBoxClothBonus4);

            for (int i = 0; i < selectedSong.ClothBonusIDList.Count; i++)
            {
                //clothComboBoxList[i].Text = ClothIDMappingList.Single(o => o.ID == selectedSong.ClothBonusIDList[i]).Cloth;
                clothComboBoxList[i].SelectedItem = ClothIDMappingList.Single(o => o.ID == selectedSong.ClothBonusIDList[i]);
            }

            //Fill Song statistic
            FillListViewSongStatistic(selectedSong);
        }

        private void FillListViewSongStatistic(Song selectedSong)
        {
            listViewSongStatistic.Items.Clear();

            string redCount = selectedSong.RhythmDataList.Count(o => o.ColorType == MemberColorHelper.Color.Red).ToString();
            string blueCount = selectedSong.RhythmDataList.Count(o => o.ColorType == MemberColorHelper.Color.Blue).ToString();
            string greenCount = selectedSong.RhythmDataList.Count(o => o.ColorType == MemberColorHelper.Color.Green).ToString();
            string yellowCount = selectedSong.RhythmDataList.Count(o => o.ColorType == MemberColorHelper.Color.Yellow).ToString();
            string purpleCount = selectedSong.RhythmDataList.Count(o => o.ColorType == MemberColorHelper.Color.Purple).ToString();
            string totalCount = selectedSong.RhythmDataList.Count().ToString();

            string[] row = { redCount, blueCount, greenCount, yellowCount, purpleCount, totalCount };
            var listViewItem = new ListViewItem(row);
            listViewSongStatistic.Items.Add(listViewItem);
            listViewSongStatistic.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewSongStatistic.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void FillMainColorComboBoxOption()
        {
            comboBoxSongMainColor.Items.Clear();

            string[] colorArray = { "Red", "Blue", "Green", "Yellow", "Purple" };
            comboBoxSongMainColor.Items.AddRange(colorArray);
        }

        private void FillClothBonusComboBoxOption()
        {
            List<ClothIDMapping> clothIDMappingList1 = new List<ClothIDMapping>();
            clothIDMappingList1.AddRange(ClothIDMappingList);
            comboBoxClothBonus1.DataSource = clothIDMappingList1;
            comboBoxClothBonus1.DisplayMember = "Cloth";
            comboBoxClothBonus1.ValueMember = "ID";

            List<ClothIDMapping> clothIDMappingList2 = new List<ClothIDMapping>();
            clothIDMappingList2.AddRange(ClothIDMappingList);
            comboBoxClothBonus2.DataSource = clothIDMappingList2;
            comboBoxClothBonus2.DisplayMember = "Cloth";
            comboBoxClothBonus2.ValueMember = "ID";

            List<ClothIDMapping> clothIDMappingList3 = new List<ClothIDMapping>();
            clothIDMappingList3.AddRange(ClothIDMappingList);
            comboBoxClothBonus3.DataSource = clothIDMappingList3;
            comboBoxClothBonus3.DisplayMember = "Cloth";
            comboBoxClothBonus3.ValueMember = "ID";

            List<ClothIDMapping> clothIDMappingList4 = new List<ClothIDMapping>();
            clothIDMappingList4.AddRange(ClothIDMappingList);
            comboBoxClothBonus4.DataSource = clothIDMappingList4;
            comboBoxClothBonus4.DisplayMember = "Cloth";
            comboBoxClothBonus4.ValueMember = "ID";
        }

        private void FillListViewRhythmData(Song selectedSong)
        {
            listViewRhythmData.Items.Clear();

            int i = 1;
            int cScore = 0;
            foreach (RhythmData rhythmData in selectedSong.RhythmDataList)
            {
                string activeSkill = SkillEffectIDMappingList.SingleOrDefault(o => o.ID == rhythmData.ActiveSkillID) == null ? "" : SkillEffectIDMappingList.SingleOrDefault(o => o.ID == rhythmData.ActiveSkillID).SkillEffect;

                cScore += (int)rhythmData.Score;
                string[] row = { i++.ToString(), rhythmData.Time.ToString(), MemberColorHelper.GetMemberColor(rhythmData.ColorType), TapTypeHelper.GetTapTypeString(rhythmData.TapType), ((int)rhythmData.Score).ToString(), cScore.ToString(), activeSkill };

                var listViewItem = new ListViewItem(row);
                listViewRhythmData.Items.Add(listViewItem);
            }

            listViewRhythmData.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewRhythmData.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void FillSongComboBoxOption(List<Member> memberList)
        {
            comboBoxHSUnitM1.Items.Clear();
            comboBoxHSUnitM2.Items.Clear();
            comboBoxHSUnitM3.Items.Clear();
            comboBoxHSUnitM4.Items.Clear();
            comboBoxHSUnitM5.Items.Clear();

            string[] memberNameArray = memberList.OrderBy(o => o.MemberNameHiragana).Select(o => o.MemberName).Distinct().ToArray();
            comboBoxHSUnitM1.Items.AddRange(memberNameArray);
            comboBoxHSUnitM2.Items.AddRange(memberNameArray);
            comboBoxHSUnitM3.Items.AddRange(memberNameArray);
            comboBoxHSUnitM4.Items.AddRange(memberNameArray);
            comboBoxHSUnitM5.Items.AddRange(memberNameArray);
        }

        private void buttonSaveSong_Click(object sender, EventArgs e)
        {
            var selectedItem = listViewSongCalculator.SelectedItems[0];

            Song selectedSong = SongList.Single(o => o.RhythmDataMappingName == selectedItem.SubItems[0].Text);
            selectedSong.SongName = textBoxSongName.Text;
            selectedSong.HighScore = int.Parse(textBoxHighScore.Text);
            selectedSong.HighScoreUnitM1 = comboBoxHSUnitM1.Text;
            selectedSong.HighScoreUnitM2 = comboBoxHSUnitM2.Text;
            selectedSong.HighScoreUnitM3 = comboBoxHSUnitM3.Text;
            selectedSong.HighScoreUnitM4 = comboBoxHSUnitM4.Text;
            selectedSong.HighScoreUnitM5 = comboBoxHSUnitM5.Text;

            selectedSong.HighScoreUnitCloth1 = comboBoxHSUnitCloth1.Text;
            selectedSong.HighScoreUnitCloth2 = comboBoxHSUnitCloth2.Text;
            selectedSong.HighScoreUnitCloth3 = comboBoxHSUnitCloth3.Text;
            selectedSong.HighScoreUnitCloth4 = comboBoxHSUnitCloth4.Text;
            selectedSong.HighScoreUnitCloth5 = comboBoxHSUnitCloth5.Text;

            selectedSong.MainColor = MemberColorHelper.GetMemberColor(comboBoxSongMainColor.Text);
            selectedSong.ClothBonusIDList = new List<int>();

            if (!string.IsNullOrEmpty(comboBoxClothBonus1.Text))
                selectedSong.ClothBonusIDList.Add(((ClothIDMapping)comboBoxClothBonus1.SelectedItem).ID);
            if (!string.IsNullOrEmpty(comboBoxClothBonus2.Text))
                selectedSong.ClothBonusIDList.Add(((ClothIDMapping)comboBoxClothBonus2.SelectedItem).ID);
            if (!string.IsNullOrEmpty(comboBoxClothBonus3.Text))
                selectedSong.ClothBonusIDList.Add(((ClothIDMapping)comboBoxClothBonus3.SelectedItem).ID);
            if (!string.IsNullOrEmpty(comboBoxClothBonus4.Text))
                selectedSong.ClothBonusIDList.Add(((ClothIDMapping)comboBoxClothBonus4.SelectedItem).ID);

            XMLHelper.SaveToXML<List<Song>>(SongList, @"Data\Song.xml");
            MessageBox.Show("Saved");
        }

        private void comboBoxUnit_SelectedValueChanged(object sender, EventArgs e)
        {
            ComboBox selectedComboBox = (ComboBox)sender;
            string selectMember = selectedComboBox.Text;

            string[] clothNameArray = MemberList.Where(o => o.MemberName == selectMember).Select(i => i.ClothName).Distinct().ToArray();

            if (selectedComboBox == comboBoxHSUnitM1)
            {
                comboBoxHSUnitCloth1.Items.Clear();
                comboBoxHSUnitCloth1.Items.AddRange(clothNameArray);
            }
            else if (selectedComboBox == comboBoxHSUnitM2)
            {
                comboBoxHSUnitCloth2.Items.Clear();
                comboBoxHSUnitCloth2.Items.AddRange(clothNameArray);
            }
            else if (selectedComboBox == comboBoxHSUnitM3)
            {
                comboBoxHSUnitCloth3.Items.Clear();
                comboBoxHSUnitCloth3.Items.AddRange(clothNameArray);
            }
            else if (selectedComboBox == comboBoxHSUnitM4)
            {
                comboBoxHSUnitCloth4.Items.Clear();
                comboBoxHSUnitCloth4.Items.AddRange(clothNameArray);
            }
            else if (selectedComboBox == comboBoxHSUnitM5)
            {
                comboBoxHSUnitCloth5.Items.Clear();
                comboBoxHSUnitCloth5.Items.AddRange(clothNameArray);
            }
        }

        private void buttonCalculateUnit_Click(object sender, EventArgs e)
        {
            var selectedItem = listViewSongCalculator.SelectedItems[0];

            Song selectedSong = SongList.Single(o => o.RhythmDataMappingName == selectedItem.SubItems[0].Text);
            List<Member> bestUnit = SongCalculator.CalculateBestUnit(ref selectedSong, MemberList, checkBoxIncludeGuest.Checked, checkBoxThreeColor.Checked, int.Parse(textBoxGuestPerformance.Text), int.Parse(textBoxFilterPerformance.Text), false);

            FillBestUnitListView(bestUnit);
            FillListViewRhythmData(selectedSong);

            //calculate high score
            double highScore = 0;
            selectedSong.RhythmDataList.ForEach(o => highScore += (o.Score));
            textBoxCalculateScore.Text = highScore.ToString();
        }

        private void FillBestUnitListView(List<Member> bestUnit)
        {
            listViewBestUnit.Items.Clear();

            foreach (Member member in bestUnit)
            {
                string[] row = { member.MemberName, member.ClothName, member.SkillEffect, member.SkillTrigger };

                var listViewItem = new ListViewItem(row);
                listViewBestUnit.Items.Add(listViewItem);
            }

            listViewBestUnit.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewBestUnit.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void buttonDeleteSong_Click(object sender, EventArgs e)
        {
            var selectedItem = listViewSongCalculator.SelectedItems[0];

            Song selectedSong = SongList.Single(o => o.RhythmDataMappingName == selectedItem.SubItems[0].Text);

            var confirmResult = MessageBox.Show("Are you sure to delete this item?", "Delete", MessageBoxButtons.YesNo);

            if (confirmResult == DialogResult.Yes)
            {
                SongList.Remove(selectedSong);
                FillSongListView(SongList);

                XMLHelper.SaveToXML<List<Song>>(SongList, @"Data\Song.xml");
                MessageBox.Show("Deleted");
            }
        }

        private void GetMemberIDMapping()
        {
            byte[] memberStream = TextFileHelper.LoadByte(@"Data\MemberIDMapping.txt");
            string memberJSON = GZipStreamHelper.UncompressString(Convert.ToBase64String(memberStream));

            MemberIDMappingList = new List<MemberIDMapping>();

            MemberIDMappingJSON.RootObject memberList = JsonConvert.DeserializeObject<MemberIDMappingJSON.RootObject>(memberJSON);
            foreach (MemberIDMappingJSON.Datum memberJSONObject in memberList.data)
            {
                MemberIDMapping memberIDMapping = new MemberIDMapping();
                memberIDMapping.ID = memberJSONObject.ID;
                memberIDMapping.Name = memberJSONObject.JP.Replace(" ", string.Empty);
                MemberIDMappingList.Add(memberIDMapping);
            }

            byte[] memberHiraganaStream = TextFileHelper.LoadByte(@"Data\MemberIDMappingHiragana.txt");
            string memberHiraganaJSON = GZipStreamHelper.UncompressString(Convert.ToBase64String(memberHiraganaStream));

            MemberIDMappingJSON.RootObject memberHiraganaList = JsonConvert.DeserializeObject<MemberIDMappingJSON.RootObject>(memberHiraganaJSON);
            for (int i = 0; i < MemberIDMappingList.Count; i++)
            {
                MemberIDMapping memberIDMapping = MemberIDMappingList.Single(o => o.ID == memberHiraganaList.data[i].ID);
                memberIDMapping.NameHiragana = memberHiraganaList.data[i].JP.Replace(" ", string.Empty);
            }
        }

        private void GetClothIDMapping()
        {
            byte[] clothStream = TextFileHelper.LoadByte(@"Data\ClothIDMapping.txt");
            string clothJSON = GZipStreamHelper.UncompressString(Convert.ToBase64String(clothStream));

            ClothIDMappingList = new List<ClothIDMapping>();

            ClothIDMappingJSON.RootObject clothList = JsonConvert.DeserializeObject<ClothIDMappingJSON.RootObject>(clothJSON);
            foreach (ClothIDMappingJSON.Datum clothJSONObject in clothList.data)
            {
                ClothIDMapping clothIDMapping = new ClothIDMapping();
                clothIDMapping.ID = clothJSONObject.ID;
                clothIDMapping.Cloth = clothJSONObject.JP;
                ClothIDMappingList.Add(clothIDMapping);
            }
        }

        private void listViewSongCalculator_KeyUp(object sender, KeyEventArgs e)
        {
            SelectSong();
        }

        private void buttonCalculateHighScoreUnit_Click(object sender, EventArgs e)
        {
            var selectedItem = listViewSongCalculator.SelectedItems[0];

            Song selectedSong = SongList.Single(o => o.RhythmDataMappingName == selectedItem.SubItems[0].Text);

            List<Member> highScoreUnit = new List<Member>();

            string memberName = comboBoxHSUnitM1.Text;
            string clothName = comboBoxHSUnitCloth1.Text;
            highScoreUnit.Add(MemberList.Where(o => o.MemberName == memberName && o.ClothName == clothName).OrderByDescending(o => o.Performance).First());

            memberName = comboBoxHSUnitM2.Text;
            clothName = comboBoxHSUnitCloth2.Text;
            highScoreUnit.Add(MemberList.Where(o => o.MemberName == memberName && o.ClothName == clothName).OrderByDescending(o => o.Performance).First());

            memberName = comboBoxHSUnitM3.Text;
            clothName = comboBoxHSUnitCloth3.Text;
            highScoreUnit.Add(MemberList.Where(o => o.MemberName == memberName && o.ClothName == clothName).OrderByDescending(o => o.Performance).First());

            memberName = comboBoxHSUnitM4.Text;
            clothName = comboBoxHSUnitCloth4.Text;
            highScoreUnit.Add(MemberList.Where(o => o.MemberName == memberName && o.ClothName == clothName).OrderByDescending(o => o.Performance).First());

            memberName = comboBoxHSUnitM5.Text;
            clothName = comboBoxHSUnitCloth5.Text;
            highScoreUnit.Add(MemberList.Where(o => o.MemberName == memberName && o.ClothName == clothName).OrderByDescending(o => o.Performance).First());

            List<Member> bestUnit = SongCalculator.CalculateBestUnit(ref selectedSong, highScoreUnit, checkBoxIncludeGuest.Checked, checkBoxThreeColor.Checked, int.Parse(textBoxGuestPerformance.Text), 0, true);

            FillBestUnitListView(bestUnit);
            FillListViewRhythmData(selectedSong);

            //calculate high score
            double highScore = 0;
            selectedSong.RhythmDataList.ForEach(o => highScore += (o.Score));
            textBoxCalculateScore.Text = highScore.ToString();
        }

        private void checkBoxColorSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxColorSelectAll.Checked)
            {
                checkBoxRed.Checked = true;
                checkBoxBlue.Checked = true;
                checkBoxGreen.Checked = true;
                checkBoxYellow.Checked = true;
                checkBoxPurple.Checked = true;
            }

            else
            {
                checkBoxRed.Checked = false;
                checkBoxBlue.Checked = false;
                checkBoxGreen.Checked = false;
                checkBoxYellow.Checked = false;
                checkBoxPurple.Checked = false;
            }
        }

        private void checkBoxStarSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxStarSelectAll.Checked)
            {
                checkBoxStar1.Checked = true;
                checkBoxStar2.Checked = true;
                checkBoxStar3.Checked = true;
                checkBoxStar4.Checked = true;
                checkBoxStar5.Checked = true;
                checkBoxStar6.Checked = true;
                checkBoxStar7.Checked = true;
            }

            else
            {
                checkBoxStar1.Checked = false;
                checkBoxStar2.Checked = false;
                checkBoxStar3.Checked = false;
                checkBoxStar4.Checked = false;
                checkBoxStar5.Checked = false;
                checkBoxStar6.Checked = false;
                checkBoxStar7.Checked = false;
            }
        }

        private void checkBoxSkillSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxSkillSelectAll.Checked)
            {
                checkBoxScoreUp.Checked = true;
                checkBoxRestore.Checked = true;
                checkBoxMental.Checked = true;
                checkBoxDecision.Checked = true;
                checkBoxOther.Checked = true;
            }

            else
            {
                checkBoxScoreUp.Checked = false;
                checkBoxRestore.Checked = false;
                checkBoxMental.Checked = false;
                checkBoxDecision.Checked = false;
                checkBoxOther.Checked = false;
            }
        }

        private void buttonAddEvent_Click(object sender, EventArgs e)
        {
            Event newEvent = new Event();
            newEvent.EventName = "New Event " + (EventList.Count() + 1);
            newEvent.EasyLP = 10;
            newEvent.NormalLP = 20;
            newEvent.HardLP = 30;
            newEvent.HSLP = 35;
            newEvent.ExpertLP = 45;

            newEvent.EasyExpGain = 30;
            newEvent.NormalExpGain = 65;
            newEvent.HardExpGain = 110;
            newEvent.HSExpGain = 135;
            newEvent.ExpertExpGain = 190;

            EventList.Add(newEvent);

            XMLHelper.SaveToXML<List<Event>>(EventList, @"Data\Event.xml");
            FillEventListView();
        }

        private void FillEventListView()
        {
            listViewEventList.Items.Clear();

            foreach (Event ev in EventList)
            {
                string[] row = { ev.EventName };
                var listViewItem = new ListViewItem(row);
                listViewEventList.Items.Add(listViewItem);
            }

            listViewEventList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewEventList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void buttonSaveEvent_Click(object sender, EventArgs e)
        {
            try
            {
                var selectedItem = listViewEventList.SelectedItems[0];

                Event selectedEvent = EventList.Single(o => o.EventName == selectedItem.SubItems[0].Text);
                selectedEvent.EventName = textBoxEventName.Text;
                selectedEvent.EventType = comboBoxEventType.Text;
                selectedEvent.Remark = textBoxEventRemark.Text;
                selectedEvent.CurrentTotalScore = int.Parse(textBoxTotalScore.Text);
                selectedEvent.CurrentAKBScore = int.Parse(textBoxAKBScore.Text);
                selectedEvent.CurrentSKEScore = int.Parse(textBoxSKEScore.Text);
                selectedEvent.CurrentNMBScore = int.Parse(textBoxNMBScore.Text);
                selectedEvent.CurrentHKTScore = int.Parse(textBoxHKTScore.Text);

                selectedEvent.CurrentTotalRanking = int.Parse(textBoxTotalRanking.Text);
                selectedEvent.CurrentAKBRanking = int.Parse(textBoxAKBRanking.Text);
                selectedEvent.CurrentSKERanking = int.Parse(textBoxSKERanking.Text);
                selectedEvent.CurrentNMBRanking = int.Parse(textBoxNMBRanking.Text);
                selectedEvent.CurrentHKTRanking = int.Parse(textBoxHKTRanking.Text);

                selectedEvent.CurrentLevel = int.Parse(textBoxLevel.Text);
                selectedEvent.CurrentLP = int.Parse(textBoxCurrentLP.Text);
                selectedEvent.CurrentExpRemain = int.Parse(textBoxExpRemain.Text);
                selectedEvent.CurrentDateTime = DateTime.Parse(textboxDateTimePicker.Text);
                selectedEvent.StoneUsed = int.Parse(textBoxStoneConsumed.Text);

                selectedEvent.EasyLP = int.Parse(textBoxLPEasy.Text);
                selectedEvent.NormalLP = int.Parse(textBoxLPNormal.Text);
                selectedEvent.HardLP = int.Parse(textBoxLPHard.Text);
                selectedEvent.HSLP = int.Parse(textBoxLPHS.Text);
                selectedEvent.ExpertLP = int.Parse(textBoxLPExpert.Text);

                selectedEvent.EasyExpGain = int.Parse(textBoxExpEasy.Text);
                selectedEvent.NormalExpGain = int.Parse(textBoxExpNormal.Text);
                selectedEvent.HardExpGain = int.Parse(textBoxExpHard.Text);
                selectedEvent.HSExpGain = int.Parse(textBoxExpHS.Text);
                selectedEvent.HSExpGain = int.Parse(textBoxExpExpert.Text);

                selectedEvent.EasyAKBScoreGain = int.Parse(textBoxScoreAKBEasy.Text);
                selectedEvent.EasySKEScoreGain = int.Parse(textBoxScoreSKEEasy.Text);
                selectedEvent.EasyNMBScoreGain = int.Parse(textBoxScoreNMBEasy.Text);
                selectedEvent.EasyHKTScoreGain = int.Parse(textBoxScoreHKTEasy.Text);

                selectedEvent.NormalAKBScoreGain = int.Parse(textBoxScoreAKBNormal.Text);
                selectedEvent.NormalSKEScoreGain = int.Parse(textBoxScoreSKENormal.Text);
                selectedEvent.NormalNMBScoreGain = int.Parse(textBoxScoreNMBNormal.Text);
                selectedEvent.NormalHKTScoreGain = int.Parse(textBoxScoreHKTNormal.Text);

                selectedEvent.HardAKBScoreGain = int.Parse(textBoxScoreAKBHard.Text);
                selectedEvent.HardSKEScoreGain = int.Parse(textBoxScoreSKEHard.Text);
                selectedEvent.HardNMBScoreGain = int.Parse(textBoxScoreNMBHard.Text);
                selectedEvent.HardHKTScoreGain = int.Parse(textBoxScoreHKTHard.Text);

                selectedEvent.HSAKBScoreGain = int.Parse(textBoxScoreAKBHS.Text);
                selectedEvent.HSSKEScoreGain = int.Parse(textBoxScoreSKEHS.Text);
                selectedEvent.HSNMBScoreGain = int.Parse(textBoxScoreNMBHS.Text);
                selectedEvent.HSHKTScoreGain = int.Parse(textBoxScoreHKTHS.Text);

                selectedEvent.ExpertAKBScoreGain = int.Parse(textBoxScoreAKBHS.Text);
                selectedEvent.ExpertSKEScoreGain = int.Parse(textBoxScoreSKEHS.Text);
                selectedEvent.ExpertNMBScoreGain = int.Parse(textBoxScoreNMBHS.Text);
                selectedEvent.ExpertHKTScoreGain = int.Parse(textBoxScoreHKTHS.Text);

                XMLHelper.SaveToXML<List<Event>>(EventList, @"Data\Event.xml");
                MessageBox.Show("Saved");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Save Error: " + ex.Message);
            }
        }

        private void listViewEventList_Click(object sender, EventArgs e)
        {
            SelectEvent();
        }

        private void SelectEvent() {
            var selectedItem = listViewEventList.SelectedItems[0];
            comboBoxEvent15Cloth.SelectedIndex = 0;
            comboBoxEvent30Cloth.SelectedIndex = 0;
            comboBoxEventDiff.SelectedIndex = 0;
            comboBoxEventRank.SelectedIndex = 0;
            
            Event selectedEvent = EventList.First(o => o.EventName == selectedItem.SubItems[0].Text);
            textBoxEventName.Text = selectedEvent.EventName;
            comboBoxEventType.Text = selectedEvent.EventType;
            textBoxEventRemark.Text = selectedEvent.Remark != null ? selectedEvent.Remark.Replace("\n", Environment.NewLine) : "";
            textBoxTotalScore.Text = selectedEvent.CurrentTotalScore.ToString();
            textBoxAKBScore.Text = selectedEvent.CurrentAKBScore.ToString();
            textBoxSKEScore.Text = selectedEvent.CurrentSKEScore.ToString();
            textBoxNMBScore.Text = selectedEvent.CurrentNMBScore.ToString();
            textBoxHKTScore.Text = selectedEvent.CurrentHKTScore.ToString();

            textBoxTotalRanking.Text = selectedEvent.CurrentTotalRanking.ToString();
            textBoxAKBRanking.Text = selectedEvent.CurrentAKBRanking.ToString();
            textBoxSKERanking.Text = selectedEvent.CurrentSKERanking.ToString();
            textBoxNMBRanking.Text = selectedEvent.CurrentNMBRanking.ToString();
            textBoxHKTRanking.Text = selectedEvent.CurrentHKTRanking.ToString();

            textBoxLevel.Text = selectedEvent.CurrentLevel.ToString();
            textBoxCurrentLP.Text = selectedEvent.CurrentLP.ToString();
            textBoxExpRemain.Text = selectedEvent.CurrentExpRemain.ToString();
            textboxDateTimePicker.Text = selectedEvent.CurrentDateTime == DateTime.MinValue ? DateTime.Now.ToString() : selectedEvent.CurrentDateTime.ToString();
            textBoxStoneConsumed.Text = selectedEvent.StoneUsed.ToString();

            textBoxLPEasy.Text = selectedEvent.EasyLP.ToString();
            textBoxLPNormal.Text = selectedEvent.NormalLP.ToString();
            textBoxLPHard.Text = selectedEvent.HardLP.ToString();
            textBoxLPHS.Text = selectedEvent.HSLP.ToString();
            textBoxLPExpert.Text = selectedEvent.ExpertLP.ToString();

            textBoxExpEasy.Text = selectedEvent.EasyExpGain.ToString();
            textBoxExpNormal.Text = selectedEvent.NormalExpGain.ToString();
            textBoxExpHard.Text = selectedEvent.HardExpGain.ToString();
            textBoxExpHS.Text = selectedEvent.HSExpGain.ToString();
            textBoxExpExpert.Text = selectedEvent.ExpertExpGain.ToString();

            textBoxScoreAKBEasy.Text = selectedEvent.EasyAKBScoreGain.ToString();
            textBoxScoreSKEEasy.Text = selectedEvent.EasySKEScoreGain.ToString();
            textBoxScoreNMBEasy.Text = selectedEvent.EasyNMBScoreGain.ToString();
            textBoxScoreHKTEasy.Text = selectedEvent.EasyHKTScoreGain.ToString();

            textBoxScoreAKBNormal.Text = selectedEvent.NormalAKBScoreGain.ToString();
            textBoxScoreSKENormal.Text = selectedEvent.NormalSKEScoreGain.ToString();
            textBoxScoreNMBNormal.Text = selectedEvent.NormalNMBScoreGain.ToString();
            textBoxScoreHKTNormal.Text = selectedEvent.NormalHKTScoreGain.ToString();

            textBoxScoreAKBHard.Text = selectedEvent.HardAKBScoreGain.ToString();
            textBoxScoreSKEHard.Text = selectedEvent.HardSKEScoreGain.ToString();
            textBoxScoreNMBHard.Text = selectedEvent.HardNMBScoreGain.ToString();
            textBoxScoreHKTHard.Text = selectedEvent.HardHKTScoreGain.ToString();

            textBoxScoreAKBHS.Text = selectedEvent.HSAKBScoreGain.ToString();
            textBoxScoreSKEHS.Text = selectedEvent.HSSKEScoreGain.ToString();
            textBoxScoreNMBHS.Text = selectedEvent.HSNMBScoreGain.ToString();
            textBoxScoreHKTHS.Text = selectedEvent.HSHKTScoreGain.ToString();

            textBoxScoreAKBExpert.Text = selectedEvent.ExpertAKBScoreGain.ToString();
            textBoxScoreSKEExpert.Text = selectedEvent.ExpertSKEScoreGain.ToString();
            textBoxScoreNMBExpert.Text = selectedEvent.ExpertNMBScoreGain.ToString();
            textBoxScoreHKTExpert.Text = selectedEvent.ExpertHKTScoreGain.ToString();
        }

        private void listViewEventList_KeyUp(object sender, KeyEventArgs e)
        {
            SelectEvent();
        }

        private void buttonTargetTotalScoreCalculate_Click(object sender, EventArgs e)
        {
            try
            {
                int currentAKBPoint = int.Parse(textBoxAKBScore.Text);
                int currentSKEPoint = int.Parse(textBoxSKEScore.Text);
                int currentNMBPoint = int.Parse(textBoxNMBScore.Text);
                int currentHKTPoint = int.Parse(textBoxHKTScore.Text);

                int targetTotalPoint = int.Parse(textBoxTargetTotalScore.Text);
                int currentLP = int.Parse(textBoxCurrentLP.Text);
                int currentLevel = int.Parse(textBoxLevel.Text);
                int currentExp = int.Parse(textBoxExpRemain.Text);
                DateTime currentDateTime = DateTime.Parse(textboxDateTimePicker.Text);

                EventGameDetail eventGameDetail = new EventGameDetail();
                eventGameDetail.DifficultyExpLPList.Add(new DifficultyExpLP(Difficulty.Easy, int.Parse(textBoxExpEasy.Text), int.Parse(textBoxLPEasy.Text)));
                eventGameDetail.DifficultyExpLPList.Add(new DifficultyExpLP(Difficulty.Normal, int.Parse(textBoxExpNormal.Text), int.Parse(textBoxLPNormal.Text)));
                eventGameDetail.DifficultyExpLPList.Add(new DifficultyExpLP(Difficulty.Hard, int.Parse(textBoxExpHard.Text), int.Parse(textBoxLPHard.Text)));
                eventGameDetail.DifficultyExpLPList.Add(new DifficultyExpLP(Difficulty.HS, int.Parse(textBoxExpHS.Text), int.Parse(textBoxLPHS.Text)));

                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Easy, GroupName.AKB, int.Parse(textBoxScoreAKBEasy.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Easy, GroupName.SKE, int.Parse(textBoxScoreSKEEasy.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Easy, GroupName.NMB, int.Parse(textBoxScoreNMBEasy.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Easy, GroupName.HKT, int.Parse(textBoxScoreHKTEasy.Text)));

                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Normal, GroupName.AKB, int.Parse(textBoxScoreAKBNormal.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Normal, GroupName.SKE, int.Parse(textBoxScoreSKENormal.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Normal, GroupName.NMB, int.Parse(textBoxScoreNMBNormal.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Normal, GroupName.HKT, int.Parse(textBoxScoreHKTNormal.Text)));

                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Hard, GroupName.AKB, int.Parse(textBoxScoreAKBHard.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Hard, GroupName.SKE, int.Parse(textBoxScoreSKEHard.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Hard, GroupName.NMB, int.Parse(textBoxScoreNMBHard.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.Hard, GroupName.HKT, int.Parse(textBoxScoreHKTHard.Text)));

                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.HS, GroupName.AKB, int.Parse(textBoxScoreAKBHS.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.HS, GroupName.SKE, int.Parse(textBoxScoreSKEHS.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.HS, GroupName.NMB, int.Parse(textBoxScoreNMBHS.Text)));
                eventGameDetail.DifficultyPointList.Add(new DifficultyPoint(Difficulty.HS, GroupName.HKT, int.Parse(textBoxScoreHKTHS.Text)));

                EventCalculator eventCalculator = new EventCalculator(LevelExperienceList);
                List<EventCalculation> eventCalculationList = eventCalculator.CalculateTotalPoint(currentAKBPoint, currentSKEPoint, currentNMBPoint, currentHKTPoint, 
                    currentLP, currentLevel, currentExp, currentDateTime, targetTotalPoint, eventGameDetail);
                FillEventCalculationListView(eventCalculationList);
            }

            catch (Exception ex)
            {
                MessageBox.Show("Error occured: " + ex.Message, "Error", MessageBoxButtons.OK);
            }
        }

        private void FillEventCalculationListView(List<EventCalculation> eventCalculationList)
        {
            listViewEventCalculation.Items.Clear();

            foreach (EventCalculation eventCalculation in eventCalculationList)
            {
                string[] row = { eventCalculation.EventDate.ToString(), eventCalculation.LP.ToString(), eventCalculation.Level.ToString(), eventCalculation.RemainExp.ToString(), eventCalculation.Difficulty.ToString(),
                               eventCalculation.TotalPoint.ToString(), eventCalculation.AKBPoint.ToString(), eventCalculation.SKEPoint.ToString(),
                               eventCalculation.NMBPoint.ToString(), eventCalculation.HKTPoint.ToString()};
                var listViewItem = new ListViewItem(row);
                listViewEventCalculation.Items.Add(listViewItem);
            }

            listViewEventCalculation.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewEventCalculation.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }

        private void buttonTargetGorupScoreCalculate_Click(object sender, EventArgs e)
        {
            try
            {
                int currentAKBPoint = int.Parse(textBoxAKBScore.Text);
                int targetAKBPoint = int.Parse(textBoxTargetAKBScore.Text);
                int currentSKEPoint = int.Parse(textBoxSKEScore.Text);
                int targetSKEPoint = int.Parse(textBoxTargetSKEScore.Text);
                int currentNMBPoint = int.Parse(textBoxNMBScore.Text);
                int targetNMBPoint = int.Parse(textBoxTargetNMBScore.Text);
                int currentHKTPoint = int.Parse(textBoxHKTScore.Text);
                int targetHKTPoint = int.Parse(textBoxTargetHKTScore.Text);

                int currentLP = int.Parse(textBoxCurrentLP.Text);
                int currentLevel = int.Parse(textBoxLevel.Text);
                int currentExp = int.Parse(textBoxExpRemain.Text);
                DateTime currentDateTime = DateTime.Parse(textboxDateTimePicker.Text);

                EventGameDetail eventGameDetail = new EventGameDetail();
                //eventGameDetail.EasyExp = int.Parse(textBoxExpEasy.Text);
                //eventGameDetail.NormalExp = int.Parse(textBoxExpNormal.Text);
                //eventGameDetail.HardExp = int.Parse(textBoxExpHard.Text);
                //eventGameDetail.HSExp = int.Parse(textBoxExpHS.Text);

                //eventGameDetail.EasyLP = int.Parse(textBoxLPEasy.Text);
                //eventGameDetail.NormalLP = int.Parse(textBoxLPNormal.Text);
                //eventGameDetail.HardLP = int.Parse(textBoxLPHard.Text);
                //eventGameDetail.HSLP = int.Parse(textBoxLPHS.Text);

                //eventGameDetail.TotalPoint.EasyPoint = int.Parse(textBoxScoreTotalEasy.Text);
                //eventGameDetail.AKBPoint.EasyPoint = int.Parse(textBoxScoreAKBEasy.Text);
                //eventGameDetail.SKEPoint.EasyPoint = int.Parse(textBoxScoreSKEEasy.Text);
                //eventGameDetail.NMBPoint.EasyPoint = int.Parse(textBoxScoreNMBEasy.Text);
                //eventGameDetail.HKTPoint.EasyPoint = int.Parse(textBoxScoreHKTEasy.Text);

                ////eventGameDetail.TotalPoint.NormalPoint = int.Parse(textBoxScoreTotalNormal.Text);
                //eventGameDetail.AKBPoint.NormalPoint = int.Parse(textBoxScoreAKBNormal.Text);
                //eventGameDetail.SKEPoint.NormalPoint = int.Parse(textBoxScoreSKENormal.Text);
                //eventGameDetail.NMBPoint.NormalPoint = int.Parse(textBoxScoreNMBNormal.Text);
                //eventGameDetail.HKTPoint.NormalPoint = int.Parse(textBoxScoreHKTNormal.Text);

                ////eventGameDetail.TotalPoint.HardPoint = int.Parse(textBoxScoreTotalHard.Text);
                //eventGameDetail.AKBPoint.HardPoint = int.Parse(textBoxScoreAKBHard.Text);
                //eventGameDetail.SKEPoint.HardPoint = int.Parse(textBoxScoreSKEHard.Text);
                //eventGameDetail.NMBPoint.HardPoint = int.Parse(textBoxScoreNMBHard.Text);
                //eventGameDetail.HKTPoint.HardPoint = int.Parse(textBoxScoreHKTHard.Text);

                ////eventGameDetail.TotalPoint.HSPoint = int.Parse(textBoxScoreTotalHS.Text);
                //eventGameDetail.AKBPoint.HSPoint = int.Parse(textBoxScoreAKBHS.Text);
                //eventGameDetail.SKEPoint.HSPoint = int.Parse(textBoxScoreSKEHS.Text);
                //eventGameDetail.NMBPoint.HSPoint = int.Parse(textBoxScoreNMBHS.Text);
                //eventGameDetail.HKTPoint.HSPoint = int.Parse(textBoxScoreHKTHS.Text);

                EventCalculator eventCalculator = new EventCalculator(LevelExperienceList);
                List<EventCalculation> eventCalculationList = eventCalculator.CalculateGroupPoint(
                    currentAKBPoint, currentSKEPoint, currentNMBPoint, currentHKTPoint,
                    currentLP, currentLevel, currentExp, currentDateTime, 
                    targetAKBPoint, targetSKEPoint, targetNMBPoint, targetHKTPoint, eventGameDetail);

                FillEventCalculationListView(eventCalculationList);
            }

            catch (Exception ex)
            {
                MessageBox.Show("Error occured: " + ex.Message, "Error", MessageBoxButtons.OK);
            }
        }

        private void buttonDeleteEvent_Click(object sender, EventArgs e)
        {
            var selectedItem = listViewEventList.SelectedItems[0];

            Event selectedEvent = EventList.Single(o => o.EventName == selectedItem.SubItems[0].Text);

            var confirmResult = MessageBox.Show("Are you sure to delete this item?", "Delete", MessageBoxButtons.YesNo);

            if (confirmResult == DialogResult.Yes)
            {
                EventList.Remove(selectedEvent);
                FillEventListView();

                XMLHelper.SaveToXML<List<Event>>(EventList, @"Data\Event.xml");
                MessageBox.Show("Deleted");
            }
        }

        private void buttonFillEventGameDetail_Click(object sender, EventArgs e)
        {
            if (buttonFillEventGameDetail.Tag == null)
            {
                MessageBox.Show("Please select a score box first.", "Error", MessageBoxButtons.OK);
                return;
            }

            else
            {
                if (comboBoxEventType.Text == "Normal")
                {
                    EventPointCalculator eventPointCalculator = new EventPointCalculator();
                    int point = eventPointCalculator.CalculatePoint(comboBoxEventDiff.Text, comboBoxEventRank.Text, int.Parse(comboBoxEvent30Cloth.Text), int.Parse(comboBoxEvent15Cloth.Text));
                    ((TextBox)buttonFillEventGameDetail.Tag).Text = point.ToString();
                }

                else if (comboBoxEventType.Text == "Group Event")
                {
                    GroupEventPointCalculator groupEventPointCalculator = new GroupEventPointCalculator();
                    int point = groupEventPointCalculator.CalculatePoint(comboBoxEventDiff.Text, comboBoxEventRank.Text, int.Parse(comboBoxEvent30Cloth.Text), int.Parse(comboBoxEvent15Cloth.Text));
                    ((TextBox)buttonFillEventGameDetail.Tag).Text = point.ToString();
                }
            }
        }

        private void textBoxGameDetailScore_Click(object sender, EventArgs e)
        {
            buttonFillEventGameDetail.Tag = (TextBox)sender;
        }

        private void textBoxScore_Leave(object sender, EventArgs e)
        {
            try {
                textBoxTotalScore.Text = (int.Parse(textBoxAKBScore.Text) + int.Parse(textBoxSKEScore.Text) + int.Parse(textBoxNMBScore.Text) + int.Parse(textBoxHKTScore.Text)).ToString();
            } catch(Exception ex) {
                MessageBox.Show("Error occured: " + ex.Message, "Error", MessageBoxButtons.OK);
            }
        }

        private void comboBoxSelectedGroup_SelectedIndexChanged(object sender, EventArgs e)
        {
            GetMember();

            List<string> groupMemberList = MemberList.Select(o => o.MemberName).Distinct().ToList();
            MemberLoveList = XMLHelper.LoadFromXML<List<MemberLove>>(@"Data\MemberLove.xml");
            MemberLoveList = MemberLoveList.Where(o => groupMemberList.Contains(o.MemberName)).ToList();

            FillMemberLoveListView();
        }
    }
}
